package Vue;
import java.awt.Dimension;
import java.awt.GraphicsEnvironment;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JSpinner;
import javax.swing.JToolBar;
import javax.swing.SpinnerModel;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import Controleur.Controleur;

/**
 * Cette class permet de créer et gérer la barre état du haut de la fenêtre principal de l'application.
 * 
 * @author Kilian Cousein et Benjamin Tardieu
 */
public class BarreEtatHaut extends JToolBar implements ChangeListener, ActionListener, FocusListener
{   
//======================================================================//
//============================ Variables ===============================//
//======================================================================//
	
	private Controleur controleur;
	
	private JLabel labelLageur = new JLabel("Largeur bordure: ");
    private SpinnerModel largeur = new SpinnerNumberModel(0, 0, 255, 1);
    private JSpinner largeurBordure = new JSpinner(largeur);
    
	private JLabel labelNbCote = new JLabel("Nombre de cotés: ");
    private SpinnerModel nbCote = new SpinnerNumberModel(6, 4, 512, 2);
    private JSpinner nbCotePolygone = new JSpinner(nbCote);
    
    private JLabel labelOpacite = new JLabel("Opacité: ");
    private SpinnerModel pourcentageOpacite = new SpinnerNumberModel(100, 0, 100, 1);
    private JSpinner opacite = new JSpinner(pourcentageOpacite);
    
	private JButton bGras = new JButton(new ImageIcon("icon/gras.png"));
	private JButton bItalique = new JButton(new ImageIcon("icon/italique.png"));    
	private JComboBox listPolice;
	private SpinnerModel valeurTaillePolice = new SpinnerNumberModel(100, 0, 100, 1);
	private JSpinner taillePolice = new JSpinner(valeurTaillePolice);

	
//======================================================================//
//========================== Constructeurs =============================//
//======================================================================//

	/**
	 * Crée une nouvelle instance de <i>BarreEtatHaut</i>.
	 *
	 * @param controleur
	 */
    public BarreEtatHaut(Controleur controleur)
    {
    	this.controleur = controleur;
    	
    	String[] fontNames = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
    	this.listPolice = new JComboBox(fontNames);
    	
    	this.largeurBordure.setName("largeurBordure");
    	this.nbCotePolygone.setName("nbCotePolygone");
    	this.opacite.setName("opacite");
    	this.listPolice.setName("listPolice");
    	this.bGras.setName("gras");
    	this.bItalique.setName("italique");  
    	this.taillePolice.setName("taillePolice");
    	
    	this.setPreferredSize(new Dimension(0,35));
    	this.largeurBordure.addChangeListener(this);
    	this.nbCotePolygone.addChangeListener(this);
    	this.taillePolice.addChangeListener(this);
    	this.opacite.addChangeListener(this);
    	this.listPolice.addActionListener(this);
    	this.bGras.addActionListener(this);
    	this.bItalique.addActionListener(this); 
    	
    	((JSpinner.DefaultEditor)this.largeurBordure.getEditor()).getTextField().addFocusListener(this);
    	((JSpinner.DefaultEditor)this.nbCotePolygone.getEditor()).getTextField().addFocusListener(this);
    	((JSpinner.DefaultEditor)this.opacite.getEditor()).getTextField().addFocusListener(this);
    	((JSpinner.DefaultEditor)this.taillePolice.getEditor()).getTextField().addFocusListener(this);
    }
    
    
//======================================================================//
//============================= Méthodes ===============================//
//======================================================================//
    
    /**
     * Cette méthode permet d'afficher ou enlever le menu permettant de modifier les caractéristiques d'un texte.
     * 
     * @param affiche Affiche le menu si <i>affiche</i> est vrai, sinon l'efface.
     */
	public void afficheMenuTexte(boolean affiche) 
	{
		if(affiche)
		{	
			this.add(listPolice);
			this.add(taillePolice);
			this.add(bGras);
			this.add(bItalique);
		}
		else
		{
			this.remove(listPolice);
			this.remove(taillePolice);
			this.remove(bGras);
			this.remove(bItalique);
			
			repaint();
		}
	}
	
	
	/**
     * Cette méthode permet d'afficher ou enlever le menu permettant de modifier l'opacité d'un motif.
     * 
     * @param affiche Affiche le menu si <i>affiche</i> est vrai, sinon l'efface.
     */
	public void afficheMenuOpacite(boolean affiche)
	{
		if(affiche)
		{	
			this.add(this.labelOpacite);
			this.add(this.opacite);
		}
		else
		{
			this.remove(this.labelOpacite);
			this.remove(this.opacite);
			
			repaint();
		}
	}
	
	
	/**
     * Cette méthode permet d'afficher ou enlever le menu permettant de modifier la largeur de la bordure.
     * 
     * @param affiche Affiche le menu si <i>affiche</i> est vrai, sinon l'efface.
     */
	public void afficheMenuLargeurBordure(boolean affiche)
	{
		if(affiche)
		{	
			this.add(this.labelLageur);
			this.add(this.largeurBordure);
		}
		else
		{
			this.remove(this.labelLageur);
			this.remove(this.largeurBordure);
			
			repaint();
		}
	}
	
	
	/**
     * Cette méthode permet d'afficher ou enlever le menu permettant de modifier le nombre de coté d'un polygone.
     * 
     * @param affiche Affiche le menu si <i>affiche</i> est vrai, sinon l'efface.
     */
	public void afficheMenuNbCotePolygone(boolean affiche)
	{
		if(affiche)
		{	
			this.add(this.labelNbCote);
			this.add(this.nbCotePolygone);
		}
		else
		{
			this.remove(this.labelNbCote);
			this.remove(this.nbCotePolygone);
			
			repaint();
		}
	}
	
	
	/**
	 * Cette méthode permet de modifier la valeur de l'opacité du motif qui sera affiché par le menu.
	 *  
	 * @param opacite Nouvelle valeur de l'opacité motif.
	 */
	public void modifierValeurMenuOpacocite(int opacite)
	{
		this.opacite.setValue(opacite);
	}
	
	
	/**
	 * Cette méthode permet de modifier la valeur de la largeur de la Bordure du motif qui sera affiché par le menu.
	 *  
	 * @param largeurBordure Nouvelle valeur de la largeur de la Bordure motif.
	 */
	public void modifierValeurMenuBordure(int largeurBordure)
	{
		this.largeurBordure.setValue(largeurBordure);
	}
	
	
	/**
	 * Cette méthode permet de modifier la valeur du nombre de coté d'un polygone qui sera affiché par le menu.
	 *  
	 * @param nbCotePolygone Nouvelle valeur du nombre de coté d'un polygone.
	 */
	public void modifierValeurMenuNbCote(int nbCotePolygone)
	{
		this.nbCotePolygone.setValue(nbCotePolygone);
	}
	
	
	/**
	 * Cette méthode permet de modifier la valeur de la police d'un texte qui sera affiché par le menu.
	 *  
	 * @param police Nouvelle valeur de la police d'un texte.
	 */
	public void modifierValeurMenuPolice(String police)
	{
		this.listPolice.setSelectedItem(police);
	}
	
	/**
	 * Cette méthode permet de modifier la valeur de la taille de la police d'un texte qui sera affiché par le menu.
	 *  
	 * @param taillePolice Nouvelle valeur de la taille de la police d'un texte.
	 */
	public void modifierValeurMenuTaillePolice(int taillePolice) 
	{
		this.taillePolice.setValue(taillePolice);
	}


//======================================================================//
//====================== Méthodes Implémentées= ========================//
//======================================================================//
	
	@Override
	public void stateChanged(ChangeEvent e)
	{
		JSpinner spinner = (JSpinner) e.getSource();

		if(((JSpinner.DefaultEditor)spinner.getEditor()).getTextField().hasFocus())
		{
			if(spinner.getName() == "largeurBordure")
			{	
				this.controleur.changerLargeurBordure(Integer.valueOf(spinner.getValue().toString()));
			}
			else if(spinner.getName() == "nbCotePolygone")
			{
				this.controleur.changerNbCotePolygone(Integer.valueOf(spinner.getValue().toString()));
			}
			else if(spinner.getName() == "opacite")
			{
				this.controleur.changerOpacite(Float.valueOf(spinner.getValue().toString()));
			}
			else if(spinner.getName() == "taillePolice")
			{
				this.controleur.changerTaillePolice(Integer.valueOf(spinner.getValue().toString()));
			}
			
			this.controleur.modifierDernierEvenement();
		}
	}


	@Override
	public void actionPerformed(ActionEvent e)
	{
		this.controleur.changerCaracteristiqueTexte(e.getSource());
	}
	
	
	@Override
	public void focusLost(FocusEvent e)
	{
		if(this.controleur.motifsDernierEvenementEgaux())
			this.controleur.supprimerDernierEvenement();
	}
	
	
	@Override
	public void focusGained(FocusEvent e)
	{
		this.controleur.modifierMotif(false);
	}
}